<template>
  <view class="genealogy-container">
    <view class="custom-navbar" @click="onBack">
      <view class="back-btn">
        <wd-icon name="arrow-left" size="22px" color="#222" />
      </view>
      <view class="navbar-title">家谱树</view>
    </view>
    <view class="member-search">
      <wd-search
        v-model="searchQuery"
        placeholder-left
        placeholder="搜索家族成员..."
        hide-cancel
        @clear="onClearSearch"
        @change="onChange"
      />
      <view v-if="searchResults.length > 0" class="search-results">
        <view
          v-for="result in searchResults"
          :key="result.id"
          class="search-item"
          @click="focusOnSearchResult(result)"
        >
          <image
            :src="
              result.photoUrl ||
              getDefaultAvatar({ gender: result.gender, birthDate: result.birthDate })
            "
            class="result-avatar"
          />
          <view class="result-info">
            <text class="result-name">{{ result.firstName }}{{ result.lastName }}</text>
            <text class="result-gender">{{ result.gender === 1 ? "男" : "女" }}</text>
          </view>
        </view>
      </view>
    </view>
    <!-- 占位元素，高度为 custom-navbar 和 member-search 的高度和 -->
    <view style="height: 5.9rem; width: 100%"></view>
    <view v-if="loading" class="loading">
      <wd-loading color="#3c9cff" size="36px" />
      <text class="loading-text">加载家谱数据中...</text>
    </view>
    <scroll-view
      v-else-if="treeData"
      :scroll-into-view="scrollToId"
      :scroll-x="true"
      :scroll-y="true"
      class="tree-scroll-container"
      id="tree-scroll-container"
      @touchstart="touchStart"
      @touchmove="touchMove"
      @touchend="touchEnd"
      @dblclick="handleDoubleClick"
    >
      <view
        ref="chartContainer"
        class="tree-canvas chartContainer"
        :style="{ transform: `scale(${scale})` }"
      >
        <!-- parent-x树状图片的 -->
        <genealogy-generation
          :menuNodeId="menuNodeId"
          :search-id="searchId"
          :person="treeData"
          :generation="1"
          :level="0"
          :index="0"
          :parent-x="0"
          :parent-y="10"
          @node-click="handleNodeClick"
          :family-members="allNodesFlat"
          @delete-node="handleDeleteNode"
          :show-action-button="false"
          @view-info="handleViewInfo"
          @action="handleTreeAction"
          @scroll-to-node="handleScrollToNode"
        />
      </view>
    </scroll-view>
    <view v-else class="empty-data">
      <wd-icon name="info-fill" size="64px" color="#ddd" />
      <text class="empty-text">暂无家谱数据</text>
    </view>
    <!-- 缩放控制器 -->
    <view v-if="!personDetail" class="zoom-controls">
      <!-- <view class="zoom-indicator">
        <text class="zoom-text">{{ Math.round(scale * 100) }}%</text>
      </view> -->
      <view class="zoom-btn" :class="{ disabled: scale >= 2.0 }" @click="zoomIn">
        <wd-icon name="add" size="20px" :color="scale >= 2.0 ? '#ccc' : '#333'" />
      </view>
      <view class="zoom-btn" :class="{ disabled: scale <= 0.3 }" @click="zoomOut">
        <wd-icon name="remove" size="20px" :color="scale <= 0.3 ? '#ccc' : '#333'" />
      </view>
      <view class="zoom-btn" @click="resetZoom">
        <wd-icon name="refresh" size="20px" />
      </view>
    </view>
    <!-- 成员详情弹窗 -->
    <wd-popup
      v-model="personDetailDialog.visible"
      class="person-detail-popup"
      @close="handleClosePersonDetail"
    >
      <wd-form v-if="personDetail" class="person-detail-form" :model="personDetail">
        <wd-cell-group border>
          <view class="person-header">
            <view v-if="personDetail.photoUrl" class="person-avatar">
              <image :src="personDetail.photoUrl" mode="aspectFill" />
            </view>
            <view v-else class="person-avatar">
              <wd-icon
                :name="personDetail.gender === 1 ? 'user' : 'female'"
                size="60px"
                color="#3c9cff"
              />
            </view>
            <view class="person-name">{{ personDetail.firstName }}{{ personDetail.lastName }}</view>
          </view>

          <wd-cell
            v-if="personDetail.nickname"
            title="昵称"
            :value="personDetail.nickname"
            icon="user"
          />
          <wd-cell title="性别" :value="personDetail.gender === 1 ? '男' : '女'" icon="user" />
          <wd-cell
            title="状态"
            :value="personDetail.alive === 1 ? '在世' : '已故'"
            icon="info-fill"
          />
          <wd-cell
            v-if="personDetail.genation"
            title="辈分"
            :value="personDetail.genation"
            icon="sort"
          />
          <wd-cell
            v-if="personDetail.occupation"
            title="职业"
            :value="personDetail.occupation"
            icon="work"
          />
          <wd-cell
            v-if="personDetail.birthPlace"
            title="出生地"
            :value="personDetail.birthPlace"
            icon="location"
          />
          <wd-cell
            v-if="personDetail.address"
            title="住址"
            :value="personDetail.address"
            icon="home"
          />
          <wd-cell
            v-if="personDetail.birthDate"
            title="出生日期"
            :value="personDetail.birthDate"
            icon="calendar"
          />
          <wd-cell
            v-if="personDetail.deathDate"
            title="逝世日期"
            :value="personDetail.deathDate"
            icon="calendar"
          />
          <wd-cell v-if="personDetail.biography" title="生平简介">
            <view class="biography">{{ personDetail.biography }}</view>
          </wd-cell>
        </wd-cell-group>
      </wd-form>
      <view v-if="!personDetail" class="popup-loading">
        <wd-loading color="#3c9cff" size="24px" />
        <text>加载中...</text>
      </view>
      <view class="popup-footer">
        <wd-button type="primary" block @click="handleClosePersonDetail">关闭</wd-button>
      </view>
    </wd-popup>
    <!-- 成员编辑弹窗 -->
    <view v-if="showEditPopup" class="popup-overlay" @click="closeEditPopup">
      <view class="popup-container" @click.stop>
        <view class="popup-header">
          <text class="popup-title">编辑成员信息</text>
          <text class="popup-close" @click="closeEditPopup">×</text>
        </view>
        <view class="popup-content">
          <text class="edit-tip">编辑功能开发中...</text>
        </view>
        <view class="popup-footer">
          <wd-button type="default" @click="closeEditPopup">关闭</wd-button>
        </view>
      </view>
    </view>

    <!-- 节点操作菜单弹窗 - 中间弹出层 -->
    <wd-popup
      v-model="showNodeMenu"
      custom-style="border-radius:32rpx;"
      position="center"
      custom-class="node-center-popup"
      :close-on-click-modal="true"
      @close="closeNodeMenu"
    >
      <view class="center-menu-container">
        <!-- 操作按钮列表 -->
        <view class="center-actions">
          <view class="action-grid">
            <view class="action-item" @click="onEditInfo(selectedNode)">
              <view class="action-icon edit-info">
                <wd-icon name="edit" size="24px" color="#fff" />
              </view>
              <text class="action-label">编辑信息</text>
            </view>
            <view
              v-if="!selectedNode?.parentId && selectedNode?.parentId !== null"
              class="action-item"
              @click="onAddParent(selectedNode)"
            >
              <view class="action-icon add-parent">
                <wd-icon name="plus" size="24px" color="#fff" />
              </view>
              <text class="action-label">新增父辈</text>
            </view>

            <view
              v-if="selectedNode?.parentId !== null"
              class="action-item"
              @click="onAddChild(selectedNode)"
            >
              <view class="action-icon add-child">
                <wd-icon name="plus" size="24px" color="#fff" />
              </view>
              <text class="action-label">新增子辈</text>
            </view>

            <view
              v-if="selectedNode?.parentId !== null"
              class="action-item"
              @click="onAddSpouse(selectedNode)"
            >
              <view class="action-icon add-spouse">
                <wd-icon name="plus" size="24px" color="#fff" />
              </view>
              <text class="action-label">新增配偶</text>
            </view>
            <view
              v-if="!selectedNode?.children || selectedNode?.children.length === 0"
              class="delete-item"
              @click="handleDeleteNode(selectedNode)"
            >
              <view class="action-icon delete-member">
                <wd-icon name="delete" size="24px" color="#fff" />
              </view>
              <text class="delete-label">删除成员</text>
            </view>
          </view>
        </view>
        <!-- 关闭按钮 -->
        <view class="center-close" @click="closeNodeMenu">
          <wd-icon name="close" size="24px" color="#999" />
        </view>
      </view>
    </wd-popup>
  </view>
</template>

<script>
import { ref, reactive } from "vue";
import PersonAPI from "@/api/genealogy/person";
import genealogyGeneration from "./components/GenealogyGeneration.vue";
import { getDefaultAvatar } from "@/utils/avatar";

import { scrollToElement, scrollToTop, isMiniProgram } from './components/scrollUtil.js';
export default {
  components: {
    genealogyGeneration,
  },
  components: {
    genealogyGeneration,
  },
  data() {
    return {
      viewType: "",
      dialogflag: true,
      loading: true,
      treeData: null,
      scale: 1,
      searchQuery: "",
      searchResults: [],
      allNodesFlat: [],
      personDetail: false,
      personDetailDialog: {
        visible: false,
        person: null,
      },
      scrollToId: "", // 用于 scroll-into-view
      targetPersonId: null,
      searchId: null, // 用于存储搜索结果的ID
      debouncedSearch: null, // 添加这一行
      menuNodeId: null, // 当前显示菜单的节点id
      startDistance: 0,
      startScale: 1,
      startX: 0,
      startY: 0,
      isMultiTouch: false,
      showEditPopup: false, // 编辑弹窗状态
      editingPerson: null, // 当前编辑的人员
      zoomHintTimer: null, // 缩放提示定时器
      showNodeMenu: false, // 节点操作菜单显示状态
      selectedNode: null, // 当前选中的节点
      userInfo: null, // 用户信息用于权限判断
    };
  },
  onLoad(options) {
    // 只负责接收参数，调用加载方法
    this.targetPersonId = options.personId || null;
    this.viewType = options.viewType || "default";
    this.loadTreeData(options.personId, this.viewType);

    // 获取用户信息用于权限判断
    try {
      this.userInfo = uni.getStorageSync("user-info");
    } catch (error) {
      console.error("获取用户信息失败:", error);
    }
  },
  watch: {
    searchId(newId) {
      if (newId) {
        this.scrollToId = "node-" + newId;
      }
    },
  },
  mounted() {
    // 在uniapp环境中，document可能不存在，移除document事件监听
    // document.addEventListener('click', this.onPageClick);
  },
  beforeDestroy() {
    // 移除document事件监听
    // document.removeEventListener('click', this.onPageClick);
    // 清理定时器
    if (this.zoomHintTimer) {
      clearTimeout(this.zoomHintTimer);
    }
  },
  methods: {
    handleClosePersonDetail() {
      this.personDetailDialog.visible = false;
      this.personDetail = null;
    },
    // 查看信息
    handleViewInfo(person) {
      // 跳转到添加子辈页面，传递父辈ID
      // uni.navigateTo({
      //   url: `/pages/genealogy/person/add-child?parentId=${person.id}`
      // });
    },
    onBack() {
      if (typeof uni !== "undefined") {
        uni.navigateBack();
      } else {
        window.history.back(); // 普通 H5 回退
      }
    },
    // 处理删除节点事件
    async handleDeleteNode(person) {
      try {
        // 判断是删除主成员还是删除配偶
        const isSpouse = person.flag !== undefined && person.flag !== null;
        const title = isSpouse ? "删除配偶确认" : "删除成员确认";
        const content = isSpouse
          ? `确定要删除配偶【${person.firstName}${person.lastName}】吗？此操作不可恢复。`
          : `确定要删除成员【${person.firstName}${person.lastName}】吗？此操作不可恢复。`;
        // 尝试使用备用方法
        const res = await new Promise((resolve, reject) => {
          uni.showModal({
            title: title,
            content: content,
            confirmText: "确认删除",
            cancelText: "取消",
            confirmColor: "#ff4444",
            success: resolve,
            fail: reject,
          });
        });
        if (res.confirm) {
          PersonAPI.deletePerson(person.id)
            .then(() => {
              // 只操作本地树结构
              uni.showToast({
                title: "删除成功",
                icon: "success",
                duration: 2000,
              });
              // 重新加载树数据
              // 删除成功后刷新树或移除节点
              this.removeNodeFromTree(this.treeData, person);
            })
            .catch((err) => {
              uni.showToast({
                title: "删除失败",
                icon: "none",
              });
            });
        } else {
          console.log("取消删除");
        }
      } catch (backupError) {
        console.error("备用确认框也失败:", backupError);
      }
    },
    // 递归移除节点
    removeNodeFromTree(tree, target) {
      if (!tree) return false;
      // 删除配偶
      if (tree.spouseList && Array.isArray(tree.spouseList)) {
        const idx = tree.spouseList.findIndex((spouse) => spouse.id === target.id);
        if (idx !== -1) {
          tree.spouseList.splice(idx, 1);
          return true;
        }
      }
      // 删除子节点
      if (tree.children && Array.isArray(tree.children)) {
        const idx = tree.children.findIndex((child) => child.id === target.id);
        if (idx !== -1) {
          tree.children.splice(idx, 1);
          return true;
        }
        // 递归子节点
        for (let child of tree.children) {
          if (this.removeNodeFromTree(child, target)) return true;
        }
      }
      return false;
    },
    handleShowMenu(nodeId) {
      // 如果点击同一个节点则关闭，否则切换
      this.menuNodeId = this.menuNodeId === nodeId ? null : nodeId;
    },
    onPageClick() {
      this.menuNodeId = null;
    },

    // 关闭节点操作菜单
    closeNodeMenu() {
      this.showNodeMenu = false;
    },

    // 检查是否显示菜单（权限判断）
    canShowMenu() {
      return this.userInfo && this.userInfo.areaCodeScope === 6;
    },
    // 处理节点点击事件，弹出操作菜单
    handleNodeClick(person) {
      this.selectedNode = person;
      this.showNodeMenu = true;
    },

    // 处理树操作事件
    handleTreeAction(data) {
      const { action, person } = data;
      console.log("树操作:", action, person);
      switch (action) {
        case "edit":
          this.editingPerson = person;
          this.showEditPopup = true;
          break;
        case "add-parent":
          // 跳转到添加父辈页面，传递子辈ID
          uni.navigateTo({
            url: `/pages/genealogy/person/add-parent?childId=${person.id}`,
          });
          break;
        case "add-child":
          // 跳转到添加子辈页面，传递父辈ID
          uni.navigateTo({
            url: `/pages/genealogy/person/add-child?parentId=${person.id}`,
          });
          break;
        case "add-spouse":
          // 跳转到添加配偶页面，传递配偶ID
          uni.navigateTo({
            url: `/pages/genealogy/person/add-spouse?spouseId=${person.id}`,
          });
          break;
        case "delete":
          console.log("删除成员:", person);
          this.handleDeleteNode(person);
          break;
      }
    },

    // 关闭编辑弹窗
    closeEditPopup() {
      this.showEditPopup = false;
      this.editingPerson = null;
    },
    // 聚焦到搜索结果（兼容H5和微信小程序）
    focusOnSearchResult(node) {
      if (!node.id) return;
      // 隐藏搜索列表
      this.searchResults = [];
      this.searchId = node.id;
      
      // 使用工具函数滚动到对应节点
      // 延迟执行以确保DOM已更新
      setTimeout(() => {
        scrollToElement(`.tree-node.highForce-${node.id}`, true, 0);
      }, 100);
    },
    // 清除搜索
    clearSearch() {
      searchQuery.value = "";
      searchResults.value = [];
    },
    // 关闭成员详情弹窗
    handleClosePersonDetail() {
      this.personDetailDialog.visible = false;
      this.personDetail = null;
    },
    
    // 处理滚动到节点事件（兼容H5和微信小程序）
    handleScrollToNode(nodeId) {
      // 使用统一的工具函数处理滚动
      scrollToElement(`.tree-node.highForce-${nodeId}`, true, 0);
    },

    // 缩放控制
    zoomIn() {
      if (this.scale < 1.5) {
        this.scale += 0.1;
        this.centerScale(); // 调整中心
        this.showZoomHint("放大");
      }
    },
    centerScale() {
      const centerX = this.$refs.chartContainer.clientWidth / 2;
      const centerY = this.$refs.chartContainer.clientHeight / 2;
      // 确保 centerX 和 centerY 是数字
      if (typeof centerX !== "number" || typeof centerY !== "number") {
        return;
      }
      // this.$refs.chartContainer.style.transform = `scale(${this.scale}) translate(-${centerX * (this.scale - 1)}px, -${centerY * (this.scale - 1)}px)`;
    },
    zoomOut() {
      if (this.scale > 0.3) {
        this.scale -= 0.1;
        this.centerScale(); // 调整中心
      }
    },
    resetZoom() {
      this.scale = 1;
      this.centerScale();
    },
    // 触摸事件处理
    touchStart(e) {
      if (e.touches.length >= 2) {
        this.isMultiTouch = true;
        this.startDistance = this.getDistance(e.touches[0], e.touches[1]);
        this.startScale = this.scale; // 记录开始时的缩放比例
      } else {
        this.isMultiTouch = false;
        // 记录单指触摸的起始位置
        this.startX = e.touches[0].clientX;
        this.startY = e.touches[0].clientY;
      }
    },
    touchMove(e) {
      if (this.isMultiTouch && e.touches.length >= 2) {
        // 双指缩放
        const currentDistance = this.getDistance(e.touches[0], e.touches[1]);
        const scale = currentDistance / this.startDistance;
        const newScale = this.startScale * scale;

        // 限制缩放范围
        if (newScale >= 0.3 && newScale <= 2.0) {
          this.scale = newScale;
          // 显示缩放提示
          this.showZoomHint("缩放");
        }
      } else if (e.touches.length === 1 && !this.isMultiTouch) {
        // 单指拖拽
        const currentX = e.touches[0].clientX;
        const currentY = e.touches[0].clientY;
        const deltaX = currentX - this.startX;
        const deltaY = currentY - this.startY;

        // 更新起始位置
        this.startX = currentX;
        this.startY = currentY;

        // 这里可以添加拖拽逻辑，但需要配合scroll-view的滚动
        // 由于使用了scroll-view，拖拽主要通过scroll-view的滚动来实现
      }
    },
    touchEnd() {
      this.isMultiTouch = false;
      this.startDistance = 0;
      this.startScale = 1;
    },

    // 计算两点之间的距离
    getDistance(p1, p2) {
      const dx = p2.clientX - p1.clientX;
      const dy = p2.clientY - p1.clientY;
      return Math.sqrt(dx * dx + dy * dy);
    },

    // 双击处理
    handleDoubleClick() {
      this.resetZoom();
    },

    // 显示缩放提示
    showZoomHint(action) {
      // 使用节流，避免频繁显示提示
      if (this.zoomHintTimer) {
        clearTimeout(this.zoomHintTimer);
      }
    },

    // 显示缩放限制提示
    showZoomLimit(message) {},

    // 节点操作菜单方法
    onAddParent(person) {
      uni.navigateTo({
        url: `/pages/genealogy/person/add-parent?childId=${person.id}`,
      });
      this.closeNodeMenu();
    },

    onAddChild(person) {
      uni.navigateTo({
        url: `/pages/genealogy/person/add-child?parentId=${person.id}`,
      });
      this.closeNodeMenu();
    },

    onAddSpouse(person) {
      uni.navigateTo({
        url: `/pages/genealogy/person/add-spouse?parentId=${person.id}`,
      });
      this.closeNodeMenu();
    },

    onEditInfo(person) {
      uni.navigateTo({
        url: `/pages/genealogy/person/edit-node?id=${person.id}&mode=edit`,
      });
      this.closeNodeMenu();
    },

    onEditSpouse(spouse) {
      uni.navigateTo({
        url: `/pages/genealogy/person/add-spouse?id=${spouse.id}&parentId=${spouse.parentId}&mode=edit&flag=${spouse.flag || 0}`,
      });
      this.closeNodeMenu();
    },

    // 初始化家谱树
    async loadTreeData(personId) {
      this.loading = true;
      try {
        let dataCopy;
        if (this.viewType === "nineFamily") {
          dataCopy = await PersonAPI.getTreeDataForFour({ personId });
        } else if (this.viewType === "eighteenGeneration") {
          dataCopy = await PersonAPI.getTreeDataForNine({ personId });
        } else {
          dataCopy = await PersonAPI.getTree({ personId });
        }
        const data = JSON.parse(JSON.stringify(dataCopy));
        if (data) this.loading = false;
        this.treeData = Array.isArray(data) && data.length > 0 ? data[0] : data;

        // 为每个节点添加默认头像
        this.treeData = this.addDefaultAvatars(this.treeData);
        this.$nextTick(() => {
          if (this.targetPersonId) {
            this.searchId = this.targetPersonId;
            this.scrollToId = "node-" + this.targetPersonId;
          }
        });
        setTimeout(() => {
          this.allNodesFlat = this.flattenTreeData(this.treeData);
          // 数据扁平化后再定位
          if (personId) {
            this.focusOnSearchResult({ id: personId });
          }
        }, 10);
      } catch (error) {
        console.error("加载家谱数据失败:", error);
      } finally {
        this.loading = false;
      }
    },
    // 递归补充默认头像
    addDefaultAvatars(node) {
      if (!node) return null;
      node.photoUrl =
        node.photoUrl || getDefaultAvatar({ gender: node.gender, birthDate: node.birthDate });
      if (node.children) {
        node.children.forEach((child) => this.addDefaultAvatars(child));
      }
      if (node.spouseList) {
        node.spouseList.forEach((spouse) => this.addDefaultAvatars(spouse));
      }
      return node;
    },
    // 扁平化树结构
    flattenTreeData(node) {
      let flat = [];
      if (node) {
        flat.push(node);
        if (node.children) {
          node.children.forEach((child) => {
            flat = flat.concat(this.flattenTreeData(child));
          });
        }
        if (node.spouseList) {
          node.spouseList.forEach((spouse) => {
            flat = flat.concat(this.flattenTreeData(spouse));
          });
        }
      }
      return flat;
    },
    onChange() {
      const query = this.searchQuery.toLowerCase();

      // 新增：如果搜索框为空，则清空搜索结果
      if (!query) {
        this.searchResults = [];
        return;
      }
      // 使用节流技术，避免频繁搜索
      if (!this.debouncedSearch) {
        this.debouncedSearch = setTimeout(() => {
          this.searchResults = this.allNodesFlat
            .filter((node) => {
              const fullName = `${node.firstName || ""}${node.lastName || ""}`.toLowerCase();
              const genation = (node.genation || "").toLowerCase();
              const nickname = (node.nickname || "").toLowerCase();
              const occupation = (node.occupation || "").toLowerCase();

              return (
                fullName.includes(query) ||
                genation.includes(query) ||
                nickname.includes(query) ||
                occupation.includes(query)
              );
            })
            .slice(0, 20); // 限制返回结果数量
          this.debouncedSearch = null; // 清除节流标志
        }, 300); // 300毫秒的节流时间
      }
    },
    onClearSearch() {
      this.searchQuery = "";
      this.searchResults = [];
    },
  },
};
</script>

<style lang="scss">
.person-detail-popup .wd-popup__content {
  width: 80% !important;
}

.genealogy-container {
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
}

.member-search {
  width: 100%;
  z-index: 100;
  position: fixed;
  top: 2.85rem;
}

/* 树形结构样式 */
.tree-scroll-container {
  flex: 1;
  width: 100%;
  height: 100%;
  background-color: #f5e9da;
}

.tree-canvas {
  position: relative;
  width: 5000rpx;
  /* 增加宽度以容纳配偶空间 */
  height: 8000rpx;
  /* 增加高度以容纳更多代 */
  transform-origin: 0 0;
  transition: transform 0.2s ease;
}

/* 缩放控制器 */
.zoom-controls {
  position: fixed;
  bottom: 120rpx;
  right: 30rpx;
  display: flex;
  flex-direction: column;
  gap: 20rpx;
  z-index: 100;
}

.zoom-indicator {
  width: 80rpx;
  height: 60rpx;
  border-radius: 40rpx;
  background-color: rgba(255, 255, 255, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  border: 2rpx solid #f0f0f0;
}

.zoom-text {
  font-size: 24rpx;
  color: #333;
  font-weight: 500;
}

.zoom-btn {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  border: 2rpx solid #f0f0f0;
  transition: all 0.2s ease;
}

.zoom-btn:active {
  transform: scale(0.95);
  background-color: #f5f5f5;
}

.zoom-btn.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.zoom-btn.disabled:active {
  transform: none;
  background-color: #fff;
}

.loading,
.empty-data {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  flex: 1;
  color: #999;
}

.loading-text,
.empty-text {
  margin-top: 20rpx;
  font-size: 28rpx;
  color: #999;
}

/* 中间弹出层样式 */
.node-center-popup {
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
}

.center-menu-container {
  background: #fff;
  border-radius: 24rpx;
  width: 600rpx;
  max-width: 90vw;
  box-shadow: 0 8rpx 48rpx rgba(0, 0, 0, 0.15);
  overflow: hidden;
  animation: centerPopupShow 0.3s ease-out;
}

@keyframes centerPopupShow {
  from {
    opacity: 0;
    transform: scale(0.8);
  }

  to {
    opacity: 1;
    transform: scale(1);
  }
}

.center-header {
  padding: 48rpx 32rpx 32rpx;
  text-align: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
}

.avatar-wrapper {
  margin-bottom: 24rpx;
}

.center-avatar {
  width: 120rpx;
  height: 120rpx;
  border-radius: 50%;
  border: 4rpx solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.2);
}

.center-avatar-placeholder {
  width: 120rpx;
  height: 120rpx;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  border: 4rpx solid rgba(255, 255, 255, 0.3);
}

.center-name {
  display: block;
  font-size: 36rpx;
  font-weight: 700;
  margin-bottom: 8rpx;
}

.center-subtitle {
  display: block;
  font-size: 28rpx;
  opacity: 0.9;
}

.center-actions {
  padding: 40rpx 32rpx;
}

.action-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24rpx;
  margin-bottom: 40rpx;
}

.action-item {
  display: flex;
  align-items: center;
  padding: 32rpx 16rpx;
  background: #f8f9fa;
  border-radius: 16rpx;
  transition: all 0.2s ease;
  flex-direction: row;
  justify-content: flex-start;
  padding: 24rpx;
}

.action-item:active {
  transform: scale(0.95);
  background: #e9ecef;
}

.action-icon {
  width: 60rpx;
  height: 60rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16rpx;
}

.action-icon.add-parent {
  background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
}

.action-icon.add-child {
  background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
}

.action-icon.add-spouse {
  background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
}

.action-icon.edit-info {
  background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
}

.action-icon.delete-member {
  background: linear-gradient(135deg, #ff4757 0%, #ff3838 100%);
}

.action-icon.delete-spouse {
  background: linear-gradient(135deg, #ff4757 0%, #ff3838 100%);
}

.action-label {
  font-size: 30rpx;
  color: #333;
  font-weight: 500;
}

.delete-section {
  border-top: 1rpx solid #eee;
  padding-top: 32rpx;
}

.delete-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28rpx;
  background: #fff5f5;
  border: 1rpx solid #fed7d7;
  border-radius: 16rpx;
  transition: all 0.2s ease;
}

.delete-item:active {
  background: #fed7d7;
  transform: scale(0.98);
}

.delete-icon {
  margin-right: 16rpx;
}

.delete-label {
  font-size: 28rpx;
  color: #ff3b30;
  font-weight: 500;
}

.center-close {
  position: absolute;
  top: 24rpx;
  right: 24rpx;
  width: 48rpx;
  height: 48rpx;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.2s;
}

.center-close:active {
  background: rgba(0, 0, 0, 0.2);
}

/* 响应式适配 */
@media screen and (max-width: 480px) {
  .center-menu-container {
    width: 85vw;
  }

  .action-grid {
    grid-template-columns: 1fr;
    gap: 16rpx;
  }

  .action-icon {
    margin-right: 20rpx;
    margin-bottom: 0;
  }
}

/* 响应式优化 */
@media (max-width: 375px) {
  .menu-item {
    padding: 28rpx 32rpx;
    font-size: 30rpx;
  }

  .menu-title {
    padding: 36rpx 24rpx 28rpx;
    font-size: 32rpx;
  }
}

/* 弹窗样式 */
.popup-footer {
  padding: 20rpx;
}

.popup-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx 0;
}

.popup-loading text {
  margin-top: 20rpx;
  font-size: 28rpx;
  color: #999;
}

.person-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 30rpx 0;
}

.person-avatar {
  width: 150rpx;
  height: 150rpx;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f0f0f0;
  margin-bottom: 20rpx;
}

.person-avatar image {
  width: 100%;
  height: 100%;
}

.person-name {
  font-size: 32rpx;
  font-weight: bold;
  color: #333;
}

.biography {
  font-size: 28rpx;
  color: #666;
  padding: 20rpx 0;
  white-space: pre-wrap;
}

.search-results {
  background-color: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  max-height: 200px;
  overflow-y: auto;
  position: absolute;
  z-index: 10;
  width: 100%;
  /* 设置宽度与搜索框对齐 */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  /* 添加阴影效果 */
}

.search-item {
  display: flex;
  align-items: center;
  padding: 10px;
  cursor: pointer;
  transition: background-color 0.3s;
  /* 添加过渡效果 */
}

.search-item:hover {
  background-color: #f0f0f0;
}

.result-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 10px;
}

.result-info {
  margin-left: 10px;
  display: flex;
  flex-direction: column;
}

.result-name {
  font-size: 16px;
  color: #333;
}

.result-gender {
  font-size: 14px;
  color: #666;
}

/* 编辑弹窗样式 */
.popup-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.popup-container {
  width: 320px;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  overflow: hidden;
}

.popup-header {
  padding: 20px 24px 16px 24px;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.popup-title {
  font-size: 18px;
  font-weight: 600;
  color: #333;
}

.popup-close {
  font-size: 24px;
  color: #999;
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  transition: background 0.2s;
}

.popup-close:hover {
  background: #f5f5f5;
}

.popup-content {
  padding: 24px;
  text-align: center;
}

.edit-tip {
  font-size: 16px;
  color: #666;
}

.popup-footer {
  padding: 16px 24px 24px 24px;
  border-top: 1px solid #f0f0f0;
  text-align: center;
}

// 家谱树头部编写样式
.custom-navbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 2.865rem;
  z-index: 1001;
  background: #fff;
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
  font-size: 16px;
  margin-bottom: 0;
}

.back-btn {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: flex;
  align-items: center;
  height: 100%;
  cursor: pointer;
}

.navbar-title {
  text-align: center;
  flex: 1;
  color: #111;
  font-weight: bold;
  font-size: 16px;
  letter-spacing: 1px;
  line-height: 2.85rem;
  height: 2.85rem;
}

.person-detail-popup {
  width: 80% !important;
  max-width: 80% !important;
  margin: 0 auto;
}
</style>
